﻿/*
 * runtimestamp.hpp
 *
 *  Created on: 2020年4月27日
 *      Author: Dylan.Gao
 */

#ifndef _DM_RUN_TIMESTAMP_HPP_
#define _DM_RUN_TIMESTAMP_HPP_

#include <dm/export.hpp>


#ifndef DM_API_MISC
#define DM_API_MISC DM_API_IMPORT
#endif

#include <ctime>
#include <dm/types.hpp>
#include <dm/timestamp.hpp>

namespace dm{

/**
 * 运行时钟时刻
 * 不受实时时钟影响
 */
class DM_API_MISC CRunTimeStamp{
public:
	typedef std::time_t sec_t; // 秒
	typedef uint64 nsec_t;	// 纳秒

public:
	CRunTimeStamp( sec_t sec=0,nsec_t nsec=0 ):m_sec(sec),m_nsec(nsec){}
	CRunTimeStamp( const CRunTimeStamp& rc ):m_sec(rc.m_sec),m_nsec(rc.m_nsec){}
	CRunTimeStamp( const volatile CRunTimeStamp& rc ):m_sec(rc.m_sec),m_nsec(rc.m_nsec){}

	inline const sec_t& secs()const{
		return m_sec;
	}

	inline const nsec_t& nsecs()const{
		return m_nsec;
	}

	inline void setSecs( sec_t secs ){
		m_sec = secs;
	}

	inline void setNSecs( nsec_t nsecs ){
		m_nsec = nsecs;
	}

	inline void setInv(){
		m_sec = 0;
		m_nsec = 0;
	}

	inline bool isInv()const{
		return m_sec==0 && m_nsec==0;
	}

	inline CRunTimeStamp& operator=( const CRunTimeStamp& rc ){
		m_sec = rc.m_sec;
		m_nsec = rc.m_nsec;
		return *this;
	}

	inline bool operator==( const CRunTimeStamp& rc )const{
		return m_sec==rc.m_sec && m_nsec==rc.m_nsec;
	}

	inline bool operator>( const CRunTimeStamp& rc )const{
		return m_sec>rc.m_sec?true:(m_sec==rc.m_sec && m_nsec>rc.m_nsec);
	}

	inline bool operator<( const CRunTimeStamp& rc )const{
		return m_sec<rc.m_sec?true:(m_sec==rc.m_sec && m_nsec<rc.m_nsec);
	}

	inline bool operator>=( const CRunTimeStamp& rc )const{
		return m_sec>rc.m_sec?true:(m_sec==rc.m_sec && m_nsec>=rc.m_nsec);
	}

	inline bool operator<=( const CRunTimeStamp& rc )const{
		return m_sec<rc.m_sec?true:(m_sec==rc.m_sec && m_nsec<=rc.m_nsec);
	}

	CRunTimeStamp operator-( const CRunTimeStamp& rc )const;

	bool isTimeout( sec_t secs,nsec_t nsecs,const CRunTimeStamp& now=cur() )const;

	inline bool isTimeout_sec( sec_t secs,const CRunTimeStamp& now=cur() )const{
		secs += m_sec;
		return secs<now.m_sec?true:(secs==now.m_sec&&m_nsec<now.m_nsec);
	}

	inline bool isTimeout_msec( nsec_t msecs,const CRunTimeStamp& now=cur() )const{
		return isTimeout(msecs/1000l,(msecs%1000l)*1000000l,now);
	}

	inline bool isTimeout_usec( nsec_t usecs,const CRunTimeStamp& now=cur() )const{
		return isTimeout(usecs/1000000l,(usecs%1000000l)*1000l,now);
	}

	inline bool isTimeout_nsec( nsec_t nsecs,const CRunTimeStamp& now=cur() )const{
		return isTimeout(nsecs/1000000000l,nsecs%1000000000l,now);
	}

	CRunTimeStamp& add( sec_t secs,nsec_t nsecs );

	inline CRunTimeStamp& addDays( sec_t days ){
		return addSecs(days*3600*24);
	}

	inline CRunTimeStamp& addHours( sec_t hours ){
		return addSecs(hours*3600);
	}

	inline CRunTimeStamp& addMinutes( sec_t minutes ){
		return addSecs(minutes*60);
	}

	inline CRunTimeStamp& addSecs( sec_t secs ){
		m_sec += secs;
		return *this;
	}

	inline CRunTimeStamp& addMsecs( nsec_t msecs ){
		return add(msecs/1000l,1000000l*(msecs%1000l));
	}

	inline CRunTimeStamp& addUsecs( nsec_t usecs ){
		return add(usecs/1000000l,1000l*(usecs%1000000l));
	}

	inline CRunTimeStamp& addNsecs( nsec_t nsecs ){
		return add(nsecs/1000000000l,nsecs%1000000000l);
	}

	CTimeStamp toTimeStamp( const CRunTimeStamp& rNow=cur(),CTimeStamp now=CTimeStamp::cur() )const;

	static CRunTimeStamp cur();
private:
	sec_t m_sec;
	nsec_t m_nsec;
};

}

#endif /* INCLUDE_DM_RUNCLOCK_HPP_ */
